package com.zshy.base.monitor.service;

import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson2.JSON;
import com.zshy.base.core.properties.SpringProperties;
import com.zshy.base.core.utils.ExceptionKit;
import com.zshy.base.monitor.domain.contract.command.SendMessageByMarkdownCommand;
import com.zshy.base.monitor.domain.contract.dto.CodeVersionDTO;
import com.zshy.base.monitor.domain.contract.enums.MonitorEnum;
import com.zshy.base.monitor.domain.contract.exception.MonitorException;
import com.zshy.base.monitor.domain.sender.factory.MonitorSendFactory;
import com.zshy.base.monitor.infras.properties.StarMonitorProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Properties;

/**
 * 代码版本服务
 *
 * @author zhouhengzhe
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeVersionService implements ApplicationListener<ApplicationEvent> {

    public static CodeVersionDTO CODE_VERSION = null;

    private final SpringProperties springProperties;

    private final MonitorSendFactory monitorSendFactory;

    private final StarMonitorProperties starMonitorProperties;

    @Override
    public void onApplicationEvent(@NonNull ApplicationEvent event) {
        if (!(event instanceof ApplicationStartedEvent || event instanceof ApplicationFailedEvent)) {
            return;
        }
        try {
            Properties p = new Properties();
            p.load(this.getClass().getClassLoader().getResourceAsStream("git.properties"));
            if (p.isEmpty()) {
                return;
            }
            CODE_VERSION = CodeVersionDTO
                    .builder()
                    .branch(p.getProperty("git.branch"))
                    .buildTime(p.getProperty("git.build.time"))
                    .buildVersion(p.getProperty("git.build.version"))
                    .commitId(p.getProperty("git.commit.id"))
                    .commitMessage(p.getProperty("git.commit.message.full"))
                    .commitUser(p.getProperty("git.commit.user.name"))
                    .commitTime(p.getProperty("git.commit.time"))
                    .build();
            log.info("代码版本 => {}", JSON.toJSONString(CODE_VERSION));
            String projectStackTrace = null;
            StringBuilder sb = new StringBuilder();
            if (event instanceof ApplicationStartedEvent) {
                sb.append(CharSequenceUtil.format("应用 **{}** 启动成功！", springProperties.getApplication().getName())).append("<br/>");
            } else {
                ApplicationFailedEvent failedEvent = (ApplicationFailedEvent) event;
                projectStackTrace = ExceptionKit.getProjectStackTraces(failedEvent.getException());
                sb.append(CharSequenceUtil.format("应用 **{}** 启动失败！", springProperties.getApplication().getName())).append("<br/>");
            }
            this.markdownTextAppend(sb, "提交ID", CODE_VERSION.getCommitId());
            this.markdownTextAppend(sb, "提交用户", CODE_VERSION.getCommitUser());
            this.markdownTextAppend(sb, "提交信息", CODE_VERSION.getCommitMessage());
            this.markdownTextAppend(sb, "提交时间", CODE_VERSION.getCommitTime());

            if (StringUtils.isNotBlank(projectStackTrace)) {
                this.markdownTextAppend(sb, "StackTrace", projectStackTrace);
            }
            if (Objects.nonNull(starMonitorProperties.getLog())) {
                //包含的情况下
                if (CollectionUtils.isNotEmpty(starMonitorProperties.getLog().getIncludeActiveProfile())
                        && starMonitorProperties.getLog().getIncludeActiveProfile().contains(springProperties.getProfiles().getActive())) {
                    sendMonitorMessage(sb);
                }
                //排除的情况下
                if (CollectionUtils.isNotEmpty(starMonitorProperties.getLog().getExcludeActiveProfile())
                        && !starMonitorProperties.getLog().getExcludeActiveProfile().contains(springProperties.getProfiles().getActive())) {
                    sendMonitorMessage(sb);
                }
            }
        } catch (Exception e) {
            throw new MonitorException(e);
        }
    }

    /**
     * 发送监控消息
     *
     * @param sb
     */
    private void sendMonitorMessage(StringBuilder sb) {
        if (Objects.nonNull(monitorSendFactory.getSender(MonitorEnum.DING_TASK))) {
            monitorSendFactory.getSender(MonitorEnum.DING_TASK).sendMessageByMarkdown(SendMessageByMarkdownCommand
                    .builder()
                    .title(CharSequenceUtil.format("应用 **{}** 启动通知", springProperties.getApplication().getName()))
                    .markdownText(sb.toString())
                    .build());
        }
        if (Objects.nonNull(monitorSendFactory.getSender(MonitorEnum.QI_WEI))) {
            monitorSendFactory.getSender(MonitorEnum.QI_WEI).sendMessageByMarkdown(SendMessageByMarkdownCommand
                    .builder()
                    .title(CharSequenceUtil.format("应用 **{}** 启动通知", springProperties.getApplication().getName()))
                    .markdownText(sb.toString())
                    .build());
        }
    }

    private void markdownTextAppend(StringBuilder sb, String key, String value) {
        if (StringUtils.isNotBlank(value)) {
            sb.append("**").append(key).append(":** ").append(value).append("<br/>");
        }
    }
}
